package com.zx.notification.producer.listener;

import com.zx.core.enums.StatusEnum;
import com.zx.notification.common.dao.NotificationChannelsConfigMapper;
import com.zx.notification.common.dao.NotificationPushTasksMapper;
import com.zx.notification.common.event.NotificationCreatedEvent;
import com.zx.notification.common.event.NotificationPushEvent;
import com.zx.notification.common.model.NotificationChannelsConfig;
import com.zx.notification.common.model.NotificationPushTasks;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 通知创建事件监听器
 * 监听通知创建事件，发布推送事件
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class NotificationCreatedEventListener {

    private final ApplicationEventPublisher eventPublisher;
    private final NotificationPushTasksMapper notificationPushTasksMapper;
    private final NotificationChannelsConfigMapper notificationChannelsConfigMapper;

    /**
     * 处理通知创建事件
     * 发布通知推送事件
     *
     * @param event 通知创建事件
     */
    @EventListener
    public void handleNotificationCreatedEvent(NotificationCreatedEvent event) {
        try {
            log.info("开始处理通知[{}]的推送事件", event.getNotificationId());

            // 获取该通知的所有推送任务
            List<NotificationPushTasks> pushTasks = notificationPushTasksMapper.selectByNotificationId(event.getNotificationId());

            if (CollectionUtils.isEmpty(pushTasks)) {
                log.info("通知[{}]没有需要推送的任务", event.getNotificationId());
                return;
            }

            // 按渠道类型分组，避免重复查询数据库
            Map<String, NotificationChannelsConfig> channelConfigMap = new HashMap<>();

            // 为每个推送任务发布推送事件
            for (NotificationPushTasks pushTask : pushTasks) {
                // 获取启用的渠道配置，以确保使用正确的MQ类型
                String channelType = pushTask.getChannelType();
                NotificationChannelsConfig channelConfig = channelConfigMap.get(channelType);

                if (channelConfig == null) {
                    channelConfig = notificationChannelsConfigMapper.selectByChannelTypeAndStatus(
                            channelType, StatusEnum.ENABLE.getCode());
                    if (channelConfig == null) {
                        log.warn("未找到渠道类型[{}]的启用配置信息", channelType);
                        continue;
                    }
                    channelConfigMap.put(channelType, channelConfig);
                }

                // 根据消费模式选择目标名称和目标类型
                String destinationName;
                String destinationType;
                if ("QUEUE".equals(pushTask.getConsumeMode())) {
                    destinationName = channelConfig.getQueueName();
                    destinationType = channelConfig.getQueueDestinationType();
                } else {
                    destinationName = channelConfig.getTopicName();
                    destinationType = channelConfig.getTopicDestinationType();
                }

                NotificationPushEvent pushEvent = new NotificationPushEvent(
                        this,
                        event.getNotificationId(),
                        pushTask.getChannelType(),
                        channelConfig.getMqType(),
                        pushTask.getConsumeMode(),
                        destinationName,
                        destinationType,
                        channelConfig.getQueueRoutingKey(),
                        channelConfig.getQueueTag(),
                        channelConfig.getPushStrategy(),
                        pushTask.getId()  // 添加任务ID
                );

                eventPublisher.publishEvent(pushEvent);
            }

            log.info("通知[{}]的{}个推送事件已发布", event.getNotificationId(), pushTasks.size());
        } catch (Exception e) {
            log.error("处理通知[{}]的推送事件时发生错误", event.getNotificationId(), e);
        }
    }
}